package com.mall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mall.common.constant.ProductConstant;
import com.mall.common.dto.SkuEsModel;
import com.mall.common.dto.SkuReductionDTO;
import com.mall.common.dto.SpuBoundsDTO;
import com.mall.common.page.PageData;
import com.mall.common.utils.ConvertUtils;
import com.mall.common.utils.Result;
import com.mall.product.dto.*;
import com.mall.common.service.impl.CrudServiceImpl;
import com.mall.product.dao.SpuInfoDao;
import com.mall.product.entity.*;
import com.mall.product.feign.CouponFeignClient;
import com.mall.product.feign.SearchFeignClient;
import com.mall.product.feign.WareFeignClient;
import com.mall.product.service.*;
import com.mall.product.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.math3.stat.descriptive.moment.Kurtosis;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * spu信息
 *
 * @author xjc xjc@163.com
 * @since 1.0.0 2022-07-17
 */
@Slf4j
@Service
public class SpuInfoServiceImpl extends CrudServiceImpl<SpuInfoDao, SpuInfoEntity, SpuInfoDTO> implements SpuInfoService {

    @Resource
    private SpuInfoDescService spuInfoDescService;
    @Resource
    private SpuImagesService spuImagesService;
    @Resource
    private SkuInfoService skuInfoService;
    @Resource
    private ProductAttrValueService productAttrValueService;
    @Resource
    private SkuImagesService skuImagesService;
    @Resource
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Resource
    private CouponFeignClient couponFeignService;
    @Resource
    private BrandService brandService;
    @Resource
    private AttrService attrService;
    @Resource
    private WareFeignClient wareFeignClient;
    @Resource
    private SearchFeignClient searchFeignClient;
    @Resource
    private CategoryService categoryService;

    @Override
    public QueryWrapper<SpuInfoEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");

        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);

        return wrapper;
    }


    @Transactional
    @Override
    public void saveAllInfo(SpuSaveVo saveVo) {
        // 保存spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtil.copyProperties(saveVo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new DateTime());
        spuInfoEntity.setUpdateTime(new DateTime());
        baseDao.insert(spuInfoEntity);

        Long spuId = spuInfoEntity.getId();
        Long brandId = spuInfoEntity.getBrandId();
        Long catelogId = spuInfoEntity.getCatelogId();
        // 保存spu图片
        List<String> images = saveVo.getImages();
        if (images.size() > 0) {
            spuImagesService.BatchSave(spuId, images);
        }
        // 保存spu描述
        List<String> decript = saveVo.getDecript();
        if (decript.size() > 0) {
            SpuInfoDescDTO spuInfoDescDTO = new SpuInfoDescDTO();
            spuInfoDescDTO.setSpuId(spuId);
            spuInfoDescDTO.setDecript(String.join(",", decript));
            spuInfoDescService.save(spuInfoDescDTO);
        }
        // 保存spu规格参数
        List<AttrDTO> baseAttrs = saveVo.getBaseAttrs();
        if (baseAttrs.size() > 0) {
            productAttrValueService.BatchSave(spuId, baseAttrs);
        }
        // 保存spu积分
        Bounds bounds = saveVo.getBounds();
        SpuBoundsDTO spuBoundsDTO = new SpuBoundsDTO();
        BeanUtil.copyProperties(bounds, spuBoundsDTO);
        spuBoundsDTO.setSpuId(spuId);
        Result result = couponFeignService.saveSpuBounds(spuBoundsDTO);
        if (result.getCode() == 0)
            log.info("saveSpuBounds 远程调用成功");
        else
            log.info("saveSpuBounds 远程调用失败");

        // 保存 sku ，及相关信息
        List<Skus> skus = saveVo.getSkus();
        if (skus.size() > 0) {
            // 保存 sku info
            skus.stream().forEach(sku -> {
                // 查找默认图片
                List<Images> defaultImgs = sku.getImages().stream().filter(img -> img.getDefaultImg() == 1).collect(Collectors.toList());
                String defaultImg = defaultImgs.size() > 0 ? defaultImgs.get(0).getImgUrl() : "";

                SkuInfoDTO skuInfoEntity = new SkuInfoDTO();
                BeanUtil.copyProperties(sku, skuInfoEntity);
                skuInfoEntity.setSpuId(spuId);
                skuInfoEntity.setBrandId(brandId);
                skuInfoEntity.setCatelogId(catelogId);
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                skuInfoService.save(skuInfoEntity);

                Long skuId = skuInfoEntity.getSkuId();
                // 保存 sku img
                List<SkuImagesEntity> imagesEntities = sku.getImages().stream().map(img -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    skuImagesEntity.setSkuId(skuId);
                    skuImagesEntity.setImgUrl(img.getImgUrl());
                    skuImagesEntity.setDefaultImg(img.getDefaultImg());
                    return skuImagesEntity;
                }).filter(item -> !StringUtils.isEmpty(item.getImgUrl())).collect(Collectors.toList());
                skuImagesService.insertBatch(imagesEntities);

                // 保存 sku 销售属性
                List<Attr> attrs = sku.getAttr();
                if (attrs.size() > 0) {
                    List<SkuSaleAttrValueEntity> saleAttrValueEntities = attrs.stream().map(attr -> {
                        SkuSaleAttrValueEntity saleAttrValueEntity = new SkuSaleAttrValueEntity();
                        saleAttrValueEntity.setAttrName(attr.getAttrName());
                        saleAttrValueEntity.setAttrValue(attr.getAttrValue());
                        saleAttrValueEntity.setAttrId(attr.getAttrId());
                        saleAttrValueEntity.setSkuId(skuId);
                        return saleAttrValueEntity;
                    }).collect(Collectors.toList());
                    skuSaleAttrValueService.insertBatch(saleAttrValueEntities);
                }
                // 保存 sku 满减等
                SkuReductionDTO skuReductionDTO = new SkuReductionDTO();
                BeanUtil.copyProperties(sku, skuReductionDTO);
                skuReductionDTO.setSkuId(skuId);
                if (skuReductionDTO.getFullCount().compareTo(new BigDecimal("0")) == 1
                        && skuReductionDTO.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
                    Result result1 = couponFeignService.saveSkuReduction(skuReductionDTO);
                    if (result1.getCode() == 0)
                        log.info("saveSkuReduction 远程调用成功");
                    else
                        log.info("saveSkuReduction 远程调用失败");
                }
            });
        }
    }

    @Override
    public PageData<SpuInfoDTO> queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<SpuInfoEntity>();
        String key = (String) params.get("key");
        if (key != null && !StringUtils.isEmpty(key))
            queryWrapper.and(q -> {
                q.eq("id", key).or().like("spu_name", key);
            });
        String status = (String) params.get("status");
        if (status != null && !StringUtils.isEmpty(status))
            queryWrapper.eq("publish_status", status);
        BigDecimal brandId = strParseBigDecimal(params.get("brandId"));
        if (brandId.compareTo(new BigDecimal("0")) > 0)
            queryWrapper.eq("brand_id", brandId);
        BigDecimal catelogId = strParseBigDecimal(params.get("catelogId"));
        if (catelogId.compareTo(new BigDecimal("0")) > 0)
            queryWrapper.eq("catelog_id", catelogId);
        IPage<SpuInfoEntity> selectPage = baseDao.selectPage(getPage(params, null, false), queryWrapper);
        List<SpuInfoDTO> dtoList = ConvertUtils.sourceToTarget(selectPage.getRecords(), SpuInfoDTO.class);
        PageData<SpuInfoDTO> pageData = new PageData<>(dtoList, selectPage.getTotal());
        return pageData;
    }

    @Transactional
    @Override
    public void up(Long spuId) {
        // 组装数据
        List<CategoryEntity> categoryList = categoryService.listAll();
        Map<String, String> categoryHashMap = categoryList.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), CategoryEntity::getName));
        List<SkuInfoEntity> skus = skuInfoService.selectBySpuId(spuId);
        List<ProductAttrValueDTO> attrValueDTOS = productAttrValueService.queryBySpuId(spuId);
        List<Long> attrIds = attrValueDTOS.stream().map(ProductAttrValueDTO::getAttrId).collect(Collectors.toList());
        HashSet<Long> searchIds = new HashSet<>(attrService.ListSearchAttrsByIds(attrIds));
        if (!(searchIds.size() > 0)) {  // 没有需要检索的属性
            baseDao.updateStatus(spuId, ProductConstant.SpuEnum.SPU_UP.getType());
        } else {
            List<SkuEsModel.Attr> collect = attrValueDTOS.stream()
                    .filter(item -> searchIds.contains(item.getAttrId()))
                    .map(item -> {
                        SkuEsModel.Attr attr = new SkuEsModel.Attr();
                        BeanUtil.copyProperties(item, attr);
                        return attr;
                    })
                    .collect(Collectors.toList());
            // 查库存
            List<Long> skuIds = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
            HashSet<Long> stockSet = null;
            Result<List<Long>> hasStock = null;
            try {
                hasStock = wareFeignClient.hasStock(skuIds);
                stockSet = new HashSet<>(hasStock.getData());
            } catch (Exception e) {
                log.error("远程获取库存服务异常：" + e.getMessage());
                stockSet = new HashSet<>();
            }

            HashSet<Long> finalStockSet = stockSet;
            List<SkuEsModel> upList = skus.stream().map(sku -> {
                SkuEsModel skuEsModel = new SkuEsModel();
                BeanUtil.copyProperties(sku, skuEsModel);
                skuEsModel.setSkuPrice(sku.getPrice());
                skuEsModel.setSkuImg(sku.getSkuDefaultImg());
                skuEsModel.setHasStock(finalStockSet.contains(sku.getSkuId()));
                // todo 热度自定义扩展
                skuEsModel.setHotScore(0L);
                // 分类
                skuEsModel.setCatalogId(sku.getCatelogId());
                skuEsModel.setCatalogName(categoryHashMap.get(sku.getCatelogId().toString()));
                // 品牌
                BrandEntity brand = brandService.selectById(sku.getBrandId());
                skuEsModel.setBrandName(brand.getName());
                skuEsModel.setBrandImg(brand.getLogo());
                // 属性
                skuEsModel.setAttrs(collect);
                return skuEsModel;
            }).collect(Collectors.toList());
            Result result = searchFeignClient.productUp(upList);
            if (result.getCode() == 0) {
                log.info("远程上架成功");
                baseDao.updateStatus(spuId, ProductConstant.SpuEnum.SPU_UP.getType());
            } else
                log.error("远程上架失败");
            // todo 接口幂等性
        }
    }

    public BigDecimal strParseBigDecimal(Object str) {
        String temp = (String) str;
        if (str == null || StringUtils.isEmpty(temp))
            return new BigDecimal("0");
        else
            try {
                return new BigDecimal(temp);
            } catch (Exception e) {
                return new BigDecimal("0");
            }
    }
}